﻿using System;
using System.Collections.Generic;
using DataBaseLibrary.DBInterfaces;
using xdb = FirebirdSql.Data.FirebirdClient;
using System.IO;

namespace DataBaseLibrary.DBObjectsFB
{
    public partial class FDBProvider : IDBProvider
    {
        private xdb.FbConnectionStringBuilder FBConSB = null;
        private string NameDB;
        private string UserName;
        private string Password;
        private xdb.FbConnection connection;

        public static xdb.FbCommand command_static = null;

        //Для работы в текущей сессии сохраняем последний загруженный или сохранённый объект и его ID

        public FDBProvider(string NameDB, string UserName, string Password)
        {
            this.NameDB = NameDB;
            this.UserName = UserName;
            this.Password = Password;
        }

        bool IDBProvider.Connect()
        {
            try
            {
                FBConSB = new xdb.FbConnectionStringBuilder();
                FBConSB.ServerType = xdb.FbServerType.Embedded;                
                FBConSB.Database = NameDB;
                FBConSB.Charset = "WIN1251";
                FBConSB.Dialect = 3;
                FBConSB.ClientLibrary = Path.GetFullPath("DataBase") + "\\fbembed.dll";
                FBConSB.UserID = UserName;
                FBConSB.Password = Password;


                connection = new xdb.FbConnection(FBConSB.ToString());
                connection.Open();
            }
            catch(SystemException)
            {
                return false;
            }

            return true;
        }

        object IDBProvider.Save(IDBObject object_db)
        {
            xdb.FbTransaction SQLTransaction = null;
            object ID = null;
            try
            {

                SQLTransaction = connection.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted);//Начали транзакцию

                var command = new xdb.FbCommand();
                command.Connection = connection;
                command.Transaction = SQLTransaction;

                command_static = command;

                //Передаём комманду в метод save объекта
                //(object_db as DBFObject).command = command;

                ID = object_db.Save();

                SQLTransaction.Commit();
                
            }
            catch (SystemException err)
            {
                throw new SystemException("Ошибка при сохранении БД с сообщением \n" + err.Message);
            }
            finally
            {
                SQLTransaction.Dispose();
            }

            return ID;      
        }

        void IDBProvider.Load(IDBObject object_db, object ID)
        {
            xdb.FbTransaction SQLTransaction = null;
            try
            {

                SQLTransaction = connection.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted);//Начали транзакцию

                var command = new xdb.FbCommand();
                command.Connection = connection;
                command.Transaction = SQLTransaction;

                //TODO: Сделать нормальной статической переменной! Или подумать, как можно сделать по-другому!!!! И во всех методах так!!!
                command_static = command;

                object_db.Load(ID);

                
            }
            catch (SystemException err)
            {
                throw new SystemException("Ошибка при загрузке БД с сообщением \n" + err.Message);
            }
            finally
            {
                SQLTransaction.Dispose();
            }
        }


        void IDBProvider.Update(IDBObject object_db)
        {
            xdb.FbTransaction SQLTransaction = null;
            try
            {
                SQLTransaction = connection.BeginTransaction(System.Data.IsolationLevel.RepeatableRead);//Начали транзакцию

                var command = new xdb.FbCommand();
                command.Connection = connection;
                command.Transaction = SQLTransaction;

                //Передаём комманду в метод save объекта
                //(object_db as DBFObject).command = command;
                command_static = command;                
                
                object_db.Update();

                SQLTransaction.Commit();
            }
            catch (SystemException err)
            {
                throw new SystemException("Ошибка при обновлении БД с сообщением \n" + err.Message);
            }
        }

        /// <summary>
        /// Удаление договора купли / продажи
        /// </summary>
        /// <param name="NumberSales"></param>
        public void DeleteSalesContract(String NumberSales)
        {
            xdb.FbTransaction SQLTransaction = null;
            try
            {
                SQLTransaction = connection.BeginTransaction(System.Data.IsolationLevel.RepeatableRead);//Начали транзакцию

                var command = new xdb.FbCommand();
                command.Connection = connection;
                command.Transaction = SQLTransaction;

                //Передаём комманду в метод save объекта
                //(object_db as DBFObject).command = command;
                command_static = command;

                command.CommandText = String.Format("delete from SALE_CONTRACT_TABLE where ID = '{0}'", NumberSales);
                command.ExecuteNonQuery();

                SQLTransaction.Commit();
            }
            catch (SystemException err)
            {
                throw new SystemException("Ошибка при обновлении БД с сообщением \n" + err.Message);
            }
        }


        /// <summary>
        /// Выполнение SQL запросов бизнес-логики
        /// </summary>
        /// <param name="query">SQL запрос</param>
        /// <returns></returns>
        List<object[]> IDBProvider.ExecQueryRead(string query)
        {
            xdb.FbTransaction SQLTransaction = null;
            try
            {
                SQLTransaction = connection.BeginTransaction(System.Data.IsolationLevel.RepeatableRead);
                //Начали транзакцию

                var command = new xdb.FbCommand();
                command.Connection = connection;
                command.Transaction = SQLTransaction;

                //Передаём комманду в метод save объекта
                //(object_db as DBFObject).command = command;
                command_static = command;

                command.CommandText = query;
                var reader = command.ExecuteReader();


                List<object[]> contractsIds = new List<object[]>();

                while (reader.Read())
                {
                    object[] objects = new object[reader.FieldCount];
                    reader.GetValues(objects);
                    contractsIds.Add(objects);
                }

                SQLTransaction.Commit();
                return contractsIds;

            }
            catch (SystemException err)
            {
                throw new Exception(err.Message);
            }
        }



        /// <summary>
        /// Выполнение SQL запросов бизнес-логики
        /// </summary>
        /// <param name="query">SQL запрос</param>
        /// <returns></returns>
        void IDBProvider.ExecQueryDml(string query)
        {
            xdb.FbTransaction SQLTransaction = null;
            try
            {
                SQLTransaction = connection.BeginTransaction(System.Data.IsolationLevel.RepeatableRead);
                //Начали транзакцию

                var command = new xdb.FbCommand();
                command.Connection = connection;
                command.Transaction = SQLTransaction;

                //Передаём комманду в метод save объекта
                //(object_db as DBFObject).command = command;
                command_static = command;

                command.CommandText = query;
                command.ExecuteNonQuery();
                
                SQLTransaction.Commit();

            }
            catch (SystemException err)
            {
                throw new Exception(err.Message);
            }
        }



        void IDBProvider.CloseConnect()
        {
            try
            {
                connection.Close();
            }
            catch (SystemException err)
            {
                throw new SystemException("Ошибка при закрытии БД с сообщением \n" + err.Message);
            }
        }

        public List<IDBObject> Search()
        {
            throw new Exception();
        }

    }
}
